package stz.flash;

import net.rim.device.api.system.Alert;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.ApplicationManagerException;
import net.rim.device.api.system.Backlight;
import net.rim.device.api.system.CodeModuleManager;
import net.rim.device.api.system.KeyListener;
import net.rim.device.api.system.RuntimeStore;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.UiApplication;
import stz.flash.main.ScreenHandle;
import stz.flash.main.strobe.model.VRController;
import stz.flash.option.AbstractGlobalKeyChoiceField;
import stz.flash.option.Option;
import stz.flash.option.app.DoubleClickStartKeyOption;
import blackberry.util.hotkey.DjDoubleClickSensor;


class LauncherKeyListener extends UiApplication implements KeyListener{
	
	private static final int EXE_TIME_INTERVAL = 2000;
	
	private static final ApplicationDescriptor newArgsDescr = new ApplicationDescriptor(
			ApplicationDescriptor
			.currentApplicationDescriptor(),
			new String[] {""});
	private static final ApplicationDescriptor cameraDescr = 
			CodeModuleManager.getApplicationDescriptors(
					CodeModuleManager.getModuleHandle("net_rim_bb_camera"))[0];
	private static final ApplicationManager appManager = ApplicationManager
			.getApplicationManager();
	private static final DjDoubleClickSensor sensor = new DjDoubleClickSensor();

	private long lastExeTime;
	private int lastGlobalKey;
	
	public LauncherKeyListener() {
		addKeyListener(this);
		//Background용 App 일때는 부팅시에 미리 실행시켜놓음
		if (Option.getIns().isBackgroundExecute()) {
			runMonkeyFlash();
		}
	}
	
	public boolean keyDown(int keycode, int time) {
		
		if (isDoubleClickAndSameKey(keycode, time)) {
			
			int startKeyInOption = DoubleClickStartKeyOption.getIns().getDoubleClickStartKey();
			if (startKeyInOption == AbstractGlobalKeyChoiceField.INT_NONE)
				return false;
			
			if (isStartKey(startKeyInOption, keycode) && isCrashApp() == false) {
				executeMonkeyFlash();
			}
		}
		
		lastGlobalKey = Keypad.key(keycode);
		return false;
	}

	private boolean isDoubleClickAndSameKey(int keycode, int time) {
		return sensor.isDoubleClick(time) && lastGlobalKey == Keypad.key(keycode);
	}
	
	private static boolean isCrashApp() {
		int processId = appManager.getForegroundProcessId();
		return isCameraForeground(processId) || isVRForeground(processId) || isThisAppDisplayed();
	}

	private static boolean isThisAppDisplayed() {
		Object runtimeData = RuntimeStore.getRuntimeStore().get(
				ScreenHandle.RUNTIME_STORE_KEY_OF_IS_DISPLAYED);
		if (runtimeData == null)
			return false;
		return ((Boolean) runtimeData).booleanValue();
	} 
	private static boolean isCameraForeground(int processId){
		return processId == appManager.getProcessId(cameraDescr);
	}
	private static boolean isVRForeground(int processId){
		return processId == appManager.getProcessId(VRController.VRDescr);
	}
	
	private boolean isStartKey(int startKeyInOption, int keycode) {
		return startKeyInOption == Keypad.key(keycode);
	}

	/**
	 *  아이콘, 단축키를 이용하는 정상적인 실행시에만
	 *  isEventThread()의 값이 True를 반환하는듯 하다
	 * 	불필요한 곳에서 이 메소드를 호출하여 
	 *  현재 클래스의 자원을 이용하려하면 문제가 생기기 쉬우니 주의 
	 */
	protected boolean acceptsForeground() {
		if (isEventThread()) {
			executeMonkeyFlash();
		}
		return false;
	}

	
	private void executeMonkeyFlash() {
		long currentTime = System.currentTimeMillis();
		if (currentTime - lastExeTime < EXE_TIME_INTERVAL) 
			return;
		runMonkeyFlash();
		startBacklightAndVibrate();
		lastExeTime = currentTime;
	}

	private void runMonkeyFlash() {
		try {
			ApplicationManager.getApplicationManager().runApplication(newArgsDescr);
		} catch (ApplicationManagerException e) { 
		}
	}
	
	private void startBacklightAndVibrate() {
		if (appManager.inStartup())
			return;
		if (Option.getIns().isVibration()) 
			Alert.startVibrate(100);
		Backlight.enable(true);
	}
	
	public boolean keyChar(char c, int i, int j) { return false; } 
	public boolean keyRepeat(int i, int j) { return false; } 
	public boolean keyStatus(int i, int j) { return false; } 
	public boolean keyUp(int i, int j) { return false; }
}